﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.CheckIn;
using Modules.Corp;
using Modules.Project.Entitys;
using Modules.System.User;
using PetaPoco;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Entity;
using PmSoft.Repositories;
using PmSoft.Utilities;

namespace Modules.Project.Repositories
{
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectGroupRepository : Repository<ProjectGroup, DefaultDbContext>
    {
        private readonly ILogger logger;
        private readonly IApplicationContext applicationContext;

        public ProjectGroupRepository(DefaultDbContext dbContext, IApplicationContext applicationContext, ILogger<ProjectGroupRepository> logger)
            : base(dbContext, applicationContext)
        {
            this.logger = logger;
            this.applicationContext = applicationContext;
        }

        /// <summary>
        /// 重写插入
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public override object Insert(ProjectGroup entity)
        {

            Sql sql = Sql.Builder;
            sql.Select("group_id")
                .From("project_group")
                .Where("project_id=@0 and name=@1 and  corp_id=@2", entity.ProjectId, entity.Name, entity.CorpId);
            int id = DbContext.FirstOrDefault<int>(sql);
            if (id > 0)
            {
                entity.IsDeleted = false;
                entity.GroupId = id;
                base.Update(entity);
                return entity;
            }
            else
                return base.Insert(entity);
        }

        public IPagedList<ProjectGroup> GetProjectGroups(ProjectGroupQuery query, int pageIndex, int pageSize)
        {
            Sql sql = Sql.Builder;
            sql.Select("group_id")
                .From("project_group");
            #region 主管单位数据权限
            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                sql.InnerJoin("project as prj").On($"project_group.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0", deptUser.IndustryType);
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }
            #endregion

            if (!string.IsNullOrEmpty(query.Keywords))
                sql.Where("project_group.name Like @0 ", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.CorpId.HasValue)
                sql.Where("corp_id=@0", query.CorpId);
            if (query.ProjectId.HasValue)
                sql.Where("project_group.project_id=@0", query.ProjectId);
            sql.OrderBy("project_group.create_time DESC");
            return GetPagingEntities(pageSize, pageIndex, sql);
        }

        public IEnumerable<ProjectGroup> GetProjectGroupsByProjectId(int projectId)
        {
            int areaVersion = EntityCacheService.GetAreaVersion("ProjectId", projectId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"ProjectGroupsByProjectId:{projectId}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("group_id")
                .From("project_group")
                .Where("project_id=@0", projectId);
                return sql;
            });
        }

        /// <summary>
        /// 搜索班组
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="keywords"></param>
        /// <returns></returns>
        public IEnumerable<ProjectGroup> SearchGoups(int projectId, string keywords)
        {
            List<int> ids = new();
            Sql sql = Sql.Builder;
            sql.Select("group_id").From("project_group");

            if (!string.IsNullOrEmpty(keywords))
                sql.Where("name like @0", "%" + StringUtility.StripSQLInjection(keywords) + "%");

            sql.Where("project_id = @0", projectId)
                .OrderBy("corp_id,is_manager_group DESC");

            ids = ids.Union(DbContext.Fetch<int>(sql)).ToList();

            if (!string.IsNullOrEmpty(keywords))
            {
                sql = Sql.Builder;
                sql.Select("g.group_id").From("person p ")
                    .InnerJoin("project_group_member as m").On("m.person_id=p.person_id")
                    .InnerJoin("project_group as g").On("m.group_id=g.group_id ")
                    .Where("p.`name` like @0 and g.project_id=@1", "%" + StringUtility.StripSQLInjection(keywords) + "%", projectId)
                    .OrderBy("g.corp_id,g.is_manager_group DESC");
                ids = ids.Union(DbContext.Fetch<int>(sql)).ToList();
            }
            return PopulateEntitiesByEntityIds(ids.Distinct());
        }
        public ProjectGroup? GetProjectGroupByPjCorpName(int projectId, int corpId, string groupName)
        {
            Sql sql = Sql.Builder.Select("group_id").From("project_group").Where("project_id=@0 AND corp_id=@1 AND name=@2  and is_deleted=0", projectId, corpId, groupName);
            var id = DbContext.FirstOrDefault<int>(sql);
            if (id == 0)
                return null;
            return Get(id);
        }

        public int GetProjectGroupCount(ProjectCheckinCountQuery query)
        {
            Sql sql = Sql.Builder;
            sql.Select("COUNT(1)")
                .From($"project_group");
            if (query.ProjectId.HasValue)
                sql.Where("project_id =@0", query.ProjectId.Value);
            if (!string.IsNullOrEmpty(query.GroupIds))
                sql.Where("group_id in(@0)", ValueUtility.ConvertToList<int>(query.GroupIds));
            sql.Where("is_deleted=0");
            return DbContext.ExecuteScalar<int>(sql);
        }

        public bool ExistsByNameAndProjectId(string name, int corpId, int projectId, int? groupId = null)
        {
            if (groupId.HasValue)
                return DbContext.Exists<ProjectGroup>("name=@0 AND project_id=@1 AND corp_id=@2 AND group_id!=@3 AND is_deleted=0", name, projectId, corpId, groupId);
            else
                return DbContext.Exists<ProjectGroup>("name=@0 AND project_id=@1 AND corp_id=@2 AND is_deleted=0 ", name, projectId, corpId);
        }
    }
}